#include "test.h"

static int count = 0;

xthread_sema_t sema;

static void *thread_changer(void *arg)
{
    int old;
    while (1) {
        xthread_sema_wait(&sema);
        count++;
        old = count;
        printf("thread: %d, count=%d\n", xthread_self(), count);
        if (old != count)
            printf("thread: %d, count=%d -> old=%d are different!\n", xthread_self(), count, old);
        xthread_sema_post(&sema);
    }
}

static void *thread_changer2(void *arg)
{
    int old;
    struct timeval tv;
    while (1) {
        gettimeofday(&tv, NULL);
        tv.tv_usec += 1000 * 200;
        if (xthread_sema_wait_timeout(&sema, &tv)) {
            printf("thread: %d, wait sema timeout\n", xthread_self());
            continue;
        }
        printf("thread: %d, wait sema no timeout\n", xthread_self());
            
        count++;
        old = count;
        printf("thread: %d, count=%d\n", xthread_self(), count);
        if (old != count)
            printf("thread: %d, count=%d -> old=%d are different!\n", xthread_self(), count, old);
        xthread_sema_post(&sema);
    }
}

static void *thread_reader(void *arg)
{
    while (1) {
        xthread_sema_wait(&sema);
        printf("thread: %d, count=%d\n", xthread_self(), count);
        xthread_sema_post(&sema);
        // xthread_usleep(1000 * 500);
        xthread_sleep(1);
    }
}

int test_sema(int argc, char *argv[])
{
    xthread_sema_init(&sema, 1);
    count = 0;
    xthread_t tid0;
    if (xthread_create(&tid0, NULL, thread_changer, "a") < 0)
        printf("xthread create failed!\n");
    
    printf("xthread create %d\n", tid0);
    xthread_t tid1;
    if (xthread_create(&tid1, NULL, thread_reader, "b") < 0)
        printf("xthread create failed!\n");
    printf("xthread create %d\n", tid1);
    xthread_t tid2;
    if (xthread_create(&tid2, NULL, thread_changer2, "c") < 0)
        printf("xthread create failed!\n");
    printf("xthread create %d\n", tid2);

    void *status;
    xthread_join(tid0, &status);
    printf("thread %x exit with %x\n", tid0, status);
    return 0;
}
